import 'dart:async';

import 'package:get/get.dart';
import 'package:in_app_purchase/in_app_purchase.dart';
import 'package:largefriends/entity/entities/lf_bool_entity.dart';
import 'package:largefriends/events/payment_product_event.dart';
import 'package:largefriends/service/manager/lf_event_helper.dart';
import 'package:largefriends/net/lf_api_url.dart';
import 'package:largefriends/net/lf_dio_util.dart';
import 'package:largefriends/utils/lf_logger.dart';
import 'package:package_info_plus/package_info_plus.dart';

import '../../events/payment_loading_event.dart';
import '../../events/payment_success_event.dart';
import '../lf_auth_service.dart';

class LfPaymentHelper {
  factory LfPaymentHelper() => _getInstance();

  static LfPaymentHelper get instance => _getInstance();

  static LfPaymentHelper? _instance;
  final List<String> sku = [
    'sub_lite_one_month',
    'sub_lite_three_months',
    'sub_lite_six_months'
  ];

  final InAppPurchase _connection = InAppPurchase.instance;
  late StreamSubscription<List<PurchaseDetails>> _subscription;
  late List<ProductDetails> products = List.empty(growable: true);
  List<ProductDetails> cacheProducts = List.empty(growable: true);
  LfAuthService authService = Get.find();

  static LfPaymentHelper _getInstance() {
    _instance ??= LfPaymentHelper._internal();
    return _instance!;
  }

  LfPaymentHelper._internal() {
    final Stream<List<PurchaseDetails>> purchaseUpdated =
        _connection.purchaseStream;
    _subscription = purchaseUpdated.listen((purchaseDetailsList) {
      if (authService.loggedIn()) {
        _listenToPurchaseUpdated(purchaseDetailsList);
      }
    }, onDone: () {
      // _subscription.cancel();
    }, onError: (error) {});
  }

  Future<void> initStoreInfo() async {
    final bool isAvailable = await _connection.isAvailable();
    if (!isAvailable) {
      return;
    }
    lfLogger.e("product request");
    await _connection.queryProductDetails(sku.toSet()).then(
        (productDetailResponse) {
      if (productDetailResponse.productDetails.isNotEmpty) {
        products.clear();
        lfLogger.e("product success");
        if (productDetailResponse.productDetails.length >= sku.length) {
          products.addAll(productDetailResponse.productDetails);
          LfEventHelper().getEvent().fire(PaymentProductEvent());
        }
      } else {
        lfLogger.e("product empty");
      }
    }, onError: (error) {
      lfLogger.e("product error");
    });
  }

  Future<void> _listenToPurchaseUpdated(
      List<PurchaseDetails> purchaseDetailsList) async {
    for (var element in purchaseDetailsList) {
      if (element.status == PurchaseStatus.pending) {
      } else {
        if (element.status == PurchaseStatus.canceled) {
          LfEventHelper().getEvent().fire(PaymentLoadingEvent(false));
        } else if (element.status == PurchaseStatus.error) {
          LfEventHelper().getEvent().fire(PaymentLoadingEvent(false));
        } else if (element.status == PurchaseStatus.purchased ||
            element.status == PurchaseStatus.restored) {
          await verifyGooglePayment(element);
        }

        if (element.pendingCompletePurchase) {
          await _connection.completePurchase(element);
          LfEventHelper().getEvent().fire(PaymentLoadingEvent(false));
        }
      }
    }
  }

  Future verifyGooglePayment(PurchaseDetails purchaseDetails) async {
    if (authService.loggedIn() == false) {
      ///防止订单太多,而且退出登录后,还在请求
      return;
    }
    Map<String, dynamic> requestData =
        await buildGooglePlayStoreData(purchaseDetails);
    await LfDio.instance
        .post<LfBoolEntity>(url: apiBuyGooglePay, params: requestData)
        .then((result) async {
      LfAuthService authService = Get.find();
      authService.currentAccount!.member = 1;
      authService.setUserEntity(authService.currentAccount);
      authService.refreshProfile();

      LfEventHelper().getEvent().fire(PaymentLoadingEvent(false));
      LfEventHelper().getEvent().fire(PaymentSuccessEvent());
    }, onError: (error) async {
      LfEventHelper().getEvent().fire(PaymentLoadingEvent(false));
    });
  }

  buildGooglePlayStoreData(PurchaseDetails purchaseDetails) async {
    Map<String, dynamic> requestMap = {};
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    requestMap.putIfAbsent("productId", () => purchaseDetails.productID);
    requestMap.putIfAbsent("packageName", () => packageInfo.packageName);
    String token =
        purchaseDetails.verificationData.serverVerificationData.toString();
    requestMap.putIfAbsent("purchaseToken", () => token);
    requestMap.putIfAbsent("userId", () => authService.currentAccount!.userId!);

    return requestMap;
  }

  Future<void> restore() async {
    LfAuthService authService = Get.find();
    await _connection.restorePurchases(
        applicationUserName: authService.currentAccount!.userId!);
  }

  Future<void> buyProduct(ProductDetails productDetails, String uid) async {
    var purchaseParam =
        PurchaseParam(productDetails: productDetails, applicationUserName: uid);
    await _connection.buyNonConsumable(purchaseParam: purchaseParam);
  }

  clear() {
    _instance = null;
    _subscription.cancel();
  }
}
